From fa177cf16926470add562ba9ac34108457b7b38f Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 6 Mar 2026 15:35:12 +0200 Subject: [PATCH] [PATCH 14/24] imap-login: Limit the number of open IMAP parser lists This prevents attackers from using a large number of '(' in a command to grow memory usage excessively. Gbp-Pq: Name CVE-2026-27857-4.patch --- src/imap-login/imap-login-client.c | 10 ++++++++-- src/imap-login/imap-login-client.h | 4 ++++ src/imap-login/imap-login-cmd-id.c | 6 +++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c index f24b90e..23c4a2f 100644 --- a/src/imap-login/imap-login-client.c +++ b/src/imap-login/imap-login-client.c @@ -379,10 +379,13 @@ static int imap_client_create(struct client *client) return -1; } + struct imap_parser_params params = { + .list_count_limit = IMAP_LOGIN_LIST_COUNT_LIMIT, + }; imap_client->parser = imap_parser_create(imap_client->common.input, imap_client->common.output, - IMAP_LOGIN_MAX_LINE_LENGTH, NULL); + IMAP_LOGIN_MAX_LINE_LENGTH, ¶ms); struct settings_instance *set_instance = settings_instance_find(client->event); if (set_instance == NULL) { set_instance = settings_instance_new( @@ -464,11 +467,14 @@ static void imap_client_starttls(struct client *client) struct imap_client *imap_client = container_of(client, struct imap_client, common); + struct imap_parser_params params = { + .list_count_limit = IMAP_LOGIN_LIST_COUNT_LIMIT, + }; imap_parser_unref(&imap_client->parser); imap_client->parser = imap_parser_create(imap_client->common.input, imap_client->common.output, - IMAP_LOGIN_MAX_LINE_LENGTH, NULL); + IMAP_LOGIN_MAX_LINE_LENGTH, ¶ms); /* CRLF is lost from buffer when streams are reopened. */ imap_client->skip_line = FALSE; diff --git a/src/imap-login/imap-login-client.h b/src/imap-login/imap-login-client.h index a62d304..34ea226 100644 --- a/src/imap-login/imap-login-client.h +++ b/src/imap-login/imap-login-client.h @@ -11,6 +11,10 @@ /* maximum length for IMAP command line. */ #define IMAP_LOGIN_MAX_LINE_LENGTH 8192 +/* Maximum number of '(' allowed in an IMAP command. Pre-login only uses + lists in the ID command. */ +#define IMAP_LOGIN_LIST_COUNT_LIMIT 1 + enum imap_client_id_state { IMAP_CLIENT_ID_STATE_LIST = 0, IMAP_CLIENT_ID_STATE_KEY, diff --git a/src/imap-login/imap-login-cmd-id.c b/src/imap-login/imap-login-cmd-id.c index 806486d..a0bb9cd 100644 --- a/src/imap-login/imap-login-cmd-id.c +++ b/src/imap-login/imap-login-cmd-id.c @@ -344,10 +344,14 @@ int cmd_id(struct imap_client *client) client->cmd_id = id = i_new(struct imap_client_cmd_id, 1); id->params = p_new(param_pool, struct imap_id_params, 1); id->params->pool = param_pool; + + struct imap_parser_params params = { + .list_count_limit = IMAP_LOGIN_LIST_COUNT_LIMIT, + }; id->parser = imap_parser_create(client->common.input, client->common.output, IMAP_LOGIN_MAX_LINE_LENGTH, - NULL); + ¶ms); id->log_reply = str_new(default_pool, 64); if (client->set->imap_literal_minus) imap_parser_enable_literal_minus(id->parser); -- 2.30.2